--
-- VHDL Architecture Reverb_lib.delay.behaviour
--
-- Created:
--          by - Siebe.UNKNOWN (SIEBJE)
--          at - 13:25:15 20-05-2008
--
-- using Mentor Graphics HDL Designer(TM) 2005.3 (Build 75)
--
library ieee;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;

entity delay is
	 generic(
		G0							: integer := 1041;
		G1							: integer := 1389;
		G2							: integer := 692;
		G3							: integer := 1023);
    port(
      clk						: in std_logic;
		clk_48k					: in std_logic;
      reset						: in std_logic;
		
		control_in				: in std_logic_vector(7 downto 0);
		control_out				: out std_logic_vector(3 downto 0);
		
      PCM_data_in				: in std_logic_vector(15 downto 0);
		PCM_data_out			: out std_logic_vector(15 downto 0)
      );
  end entity delay;

--
architecture behaviour of delay is
   
  component fifo_1k_16 is
	port (
		clk			: in std_logic;
		din			: in std_logic_VECTOR(15 downto 0);
		rd_en			: in std_logic;
		rst			: in std_logic;
		wr_en			: in std_logic;
		data_count	: out std_logic_VECTOR(9 downto 0);
		dout			: out std_logic_VECTOR(15 downto 0);
		empty			: out std_logic;
		full			: out std_logic
		);
	end component fifo_1k_16;
  
	signal last_48k_clock	: std_logic := '0';
	signal read_enable		: std_logic := '0';
	signal write_enable		: std_logic := '0';
	signal reset_n				: std_logic := '1';
	signal fifo_empty			: std_logic := '0';
	signal fifo_full			: std_logic := '0';
	signal data_count			: std_logic_vector(9 downto 0);
	
	signal output_clk			: std_logic := '0';
	signal last_output_clk	: std_logic := '0';
	signal clk_counter		: integer 	:= 0;
	signal output_counter	: integer 	:= 0;
	
	signal maximum				: integer	:= G3;			--length of half of a 48k period
	signal index				: integer	:= 0;
	
	type array_3 is array (0 to 2) of integer;
	constant MAX				: array_3	:= (G0, G1, G2);
	
	constant COUNT_MAX		: integer	:= 1023;
	
begin
	control_out(0) 			<= fifo_full;
	control_out(1) 			<= fifo_empty;
	control_out(3 downto 2) <= "10";

	reset_n		<= not reset;

	Fifo0: fifo_1k_16 port map(	clk			=> clk,			--FIFO runs on 48kHz clock  
											din			=> PCM_data_in,
											rd_en			=> read_enable,
											rst			=> reset_n,
											wr_en			=> write_enable,
											data_count	=> data_count,
											dout			=> PCM_data_out,
											empty			=> fifo_empty,
											full			=> fifo_full
										);

	generate_output_clk_p: process (clk, reset)
	begin
		if reset = '0' then
			output_clk <= '0';
			clk_counter <= 0;
		elsif clk'event and clk = '1' then
			if clk_counter = maximum then
				output_clk 		<= not output_clk;
				clk_counter 	<= 0;
			else
				clk_counter <= clk_counter + 1;
			end if;
		end if;
	end process;
	
	input_p: process (clk, reset)
	begin
		if (reset = '0') then
			write_enable	<= '0';
			last_48k_clock	<= '0';
		elsif (clk'event and clk = '1') then
			if not(last_48k_clock = clk_48k) and clk_48k = '1' then	--clk_48k'posedge
				write_enable <= '1';											--write data to FIFO @ posedge
			else
				write_enable <= '0';
			end if;
			last_48k_clock <= clk_48k;
		end if;
	end process;
	
	output_p: process (clk, reset)
	begin
		if (reset = '0') then
			read_enable			<= '0';
			index 				<= 0;
			last_output_clk 	<= '0';
			maximum				<= MAX(0);
		elsif (clk'event and clk = '1') then
			if not(last_output_clk = output_clk) and output_clk = '1' then	--output_clk'posedge
				read_enable	<= '1';
			
				if output_counter = COUNT_MAX - 2 then
					index <= index + 1;
					output_counter <= output_counter + 1;
				elsif output_counter = COUNT_MAX - 1 and index = 3 then
					index <= 0;
					output_counter <= output_counter + 1;
				elsif output_counter = COUNT_MAX then								--hold the same clock for 1023 cycles
					maximum <= MAX(index);
					output_counter <= 0;
				else
					output_counter <= output_counter + 1;
				end if;
			else
				read_enable <= '0';
			end if;
			
			last_output_clk <= output_clk;
		end if;
	end process;
    
END ARCHITECTURE behaviour;
